package com.wmb.controller;

import com.wmb.bean.UserInfoBean;
import com.wmb.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.UUID;


@Controller
public class UserController {

    // 依赖注入
    @Resource
    //需要创建setter方法
    //这里注入的是接口，不是对应的实现类，会自动创建对象，下方可以直接调用
    private UserService userService;

    @Resource
    HttpServletRequest request;


    ///////////////////////////////////////////页面跳转的不同方式///////////////////////////////////////////
    //进行页面的登录操作（连接给定的页面，并跳转到指定的页面）
    //@RequestMapping 是 Spring Web 应用程序中最常被用到的注解之一。这个注解会将 HTTP 请求映射到 MVC 和 REST 控制器的处理方法上
    @RequestMapping("/login")
    //请求方法返回String类型
    //@RequestParam("index页面的name"):若传递的参数不与index页面中的变量名一致时，用@RequestParam("username")注解代替不一样的变量名 userPsw
    public String doLogin(@RequestParam("username") String userName, @RequestParam("userpsw") String userPsw) {
        System.out.println("正在进行登录操作:" + userName + ";密码：" + userPsw);
        // 返回的视图的路径：WEB-INF/pages/logined.jsp
        // 通过springmvc的视图解析器：会自动附加 前缀 /WEB-INF/pages/ 和后缀 .jsp，所以只需要返回中间部分即可；
        //跳转到登录成功的页面
        return "logined";
    }

    @RequestMapping("/login2")
    public String doLogin2(UserInfoBean userInfo) {
        System.out.println("正在进行登录操作:" + userInfo.getUsername() + ";密码：" + userInfo.getUserpsw());
        // 调用service层进行业务逻辑处理，通过service类中方法的返回结果去对页面进行调用
        boolean canLogin = userService.doLogin(userInfo);
        // 根据查询结果集进行跳转
        if (canLogin) {
            // 登录成功
            // 返回的视图的路径：WEB-INF/pages/logined.jsp
            // 通过springmvc的视图解析器：会自动附加 前缀 /WEB-INF/pages/ 和后缀 .jsp，所以只需要返回中间部分即可；
            HttpServletRequest request1 = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            // 设置session缓存
            request1.setAttribute("userLoginedName", userInfo.getUsername());
            return "logined";
        }else{
            // 登录失败，跳回登录页面
            //../../index:要从logined页面跳回index页面，所以要找到WEBAPP层
            return "../../index";
        }
    }

    //推荐使用该方式
    //请求方法返回ModelAndView对象类型
    @RequestMapping("/login3")
    public ModelAndView doLogin3(UserInfoBean userInfo) {

        //创建一个ModelAndView的对象，用于使用返回数据
        ModelAndView modelAndView = new ModelAndView();
        System.out.println("正在进行登录操作:" + userInfo.getUsername() + ";密码：" + userInfo.getUserpsw());
        // 调用service层进行业务逻辑处理
        boolean canLogin = userService.doLogin(userInfo);
        // 根据查询结果集进行跳转
        if (canLogin) {
            // 登录成功
            // 返回的视图的路径：WEB-INF/pages/logined.jsp
            // 通过springmvc的视图解析器：会自动附加 前缀 /WEB-INF/pages/ 和后缀 .jsp，所以只需要返回中间部分即可；

            //设置要返回的页面视图：setViewName()方法
            modelAndView.setViewName("logined");
            //使用modal进行数据缓存
            modelAndView.addObject("userLogineName","userInfo.getUsername()");
        }else{
            // 登录失败，跳回登录页面
            //../../index:要从logined页面跳回index页面，所以要找到webapp层

            //设置要返回的页面视图setViewName()方法
            modelAndView.setViewName("../../index");
        }
        // 返回值
        return modelAndView;

    }


    //使用servlet进行页面的登录操作，上面的方法本质是servlet，只是对servlet进行了封装，这里有把这个封装拆开了
    //请求方法返回ModelAndView对象类型
    @RequestMapping("/login4")
    public String doLogin4(UserInfoBean userInfo, HttpServletRequest request) {

        System.out.println("正在进行登录操作:" + userInfo.getUsername() + ";密码：" + userInfo.getUserpsw());

        // 调用service层进行业务逻辑处理
        boolean canLogin = userService.doLogin(userInfo);
        System.out.println("使用servlet注入的方式获取表单数据：" + request.getParameter("username"));

        // 根据查询结果集进行跳转
        if (canLogin) {
            // 登录成功
            // 返回的视图的路径：WEB-INF/pages/logined.jsp
            // 通过springmvc的视图解析器：会自动附加 前缀 /WEB-INF/pages/ 和后缀 .jsp，所以只需要返回中间部分即可；

            //使用session进行数据缓存
            request.getSession().setAttribute("userLoginedName", userInfo.getUsername());
            System.out.println("使用session缓存的数据：" + userInfo.getUsername());
            return "logined";
        } else {
            // 登录失败，跳回登录页面
            //../../index:要从logined页面跳回index页面，所以要找到webapp层

            return "../../index";
        }
    }
    ///////////////////////////////////////////////////////////////////////


    //对静态资源(页面的跳转)的跳转
    /**
     * 通过后台进行跳转处理
     *
     * @param pg 跳转的视图名字
     * @return 目标视图名
     */
    @RequestMapping("/jump")
    public String jump(String pg) {
        return pg;
    }


    @RequestMapping("/addAndUpdateUserInfo")
    //@RequestParam("username") MultipartFile multipartFile:将前台页面上传的文件对象映射到multipartFile对象上（接收页面传入的字节流）
    public String addAndUpdateUserInfo(UserInfoBean userInfoBean, @RequestParam("file_userimg") MultipartFile multipartFile) {

        System.out.println("userInfobean::::");
        System.out.println(userInfoBean);
    ////////////////////////////////////可被简化的代码（开始处）//////////////////////////////////////////////////
        ///////////////////文件上传处理////////////////////

       /*
            步骤：1. 获取服务器上的项目的根目录地址
                 2. 把要上传的文件的目录放在静态资源解析的文件夹中，以便以后使用,需要进行文件拼接
                 3. 创建目录：判断这个要上传文件的存放目录是否存在，如果不存在，则创建这个目录，然后在上传文件（先有目录再有文件）
                 4. 获取原文件的文件后缀
                 5. 为原文件生成一个新的文件名
                 6. 将重新命名的文件转化为文件流
                 7. 将文件流进行上传

            注意：对文件进行上传后，被上传的文件进入到target中，若进行了clean，则target文件就会消失（再启动才会有），上传的文件也会消失
        */
        System.out.println("上传的文件对象：");
        System.out.println(multipartFile.getOriginalFilename());

        //
        //
        /*
            通过System工具类获取当前服务器发布的地址,获取的是项目在服务器发布的根目录地址
                使用 System.getProperty("server.basePath"),获取服务器的绝对路径地址，
                需要在web.xml中配置 org.springframework.web.util.WebAppRootListener 监听器
         */
        // 获取服务器上的项目的根目录地址
        String strBasePath = System.getProperty("server.basePath");
        System.out.println("服务器根据路地址：" + strBasePath);

        // 定义上传文件的目录名
        String strUploadfiles = "uploadfiles";
        // 把要上传的文件的目录放在静态资源解析的文件夹中，以便以后使用,需要进行文件拼接
        String strfullDirectoryPath = strBasePath + File.separator + "static" + File.separator
                + strUploadfiles + File.separator;

        //判断这个上传文件的存放目录是否存在，如果不存在，则创建这个目录，然后在上传文件（先有目录再有文件）
        File uploadDirectory = new File(strfullDirectoryPath);
        if (!uploadDirectory.exists()) {
            // 创建目录
            uploadDirectory.mkdirs();
        }

        // 给上传文件进行重新命名：先获取原文件名，并通过原文件名 sssxxx.jpg 获取到文件的后缀
        // 用于获取原文件名
        String strOriginalFilename = multipartFile.getOriginalFilename();
        // 用于获取上传源文件的后缀
        String strFileSufix = StringUtils.substringAfterLast(strOriginalFilename, ".");
        System.out.println(strFileSufix);
        // 使用UUID生成新的文件名（防止重复）
        String strFileNewName = "userimg" + UUID.randomUUID().toString() + "." + strFileSufix;
        // 创建要上传的新文件对象：文件目录+File.separator+文件名
        String uploadNewFileName = strfullDirectoryPath + File.separator + strFileNewName;
        //将要上传的新文件对象new File转为文件数据流
        File uploadNewFile = new File(uploadNewFileName);


        try {
            // 将创建的文件进行上传
            multipartFile.transferTo(uploadNewFile);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("文件上传失败：" + e.getMessage());
        }
   ///////////////////////////////////被被简化的代码（结束处）///////////////////////////////////////////////////

        //获取文件的相对路径，保存到数据库（static文件下的）
        userInfoBean.setUserimg("static" + File.separator
                + strUploadfiles + File.separator + strFileNewName);
        // 调用service层进行业务逻辑处理
        int i = userService.addAndUpdateUserInfo(userInfoBean);

        if (i > 0) {
            // 保存成功
            return "userInfo/UserInfoAddDetail";
        } else {
            // 保存失败
            return "userInfo/UserInfoAdd";
        }
    }

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}
